package com.kuaimacode.kframework.admin.services.agent;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.andyczy.java.excel.ExcelUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.kuaimacode.kframework.admin.services.finance.AgentAccountDetailService;
import com.kuaimacode.kframework.admin.services.role.SysAgentRoleService;
import com.kuaimacode.kframework.admin.services.sysparam.SysParamService;
import com.kuaimacode.kframework.admin.util.SessionUtil;
import com.kuaimacode.kframework.admin.vo.request.AgentOrderReq;
import com.kuaimacode.kframework.admin.vo.response.AgentOrderResp;
import com.kuaimacode.kframework.common.Constant;
import com.kuaimacode.kframework.constants.SysAgentUserPasswordConstants;
import com.kuaimacode.kframework.exception.ErrorEnum;
import com.kuaimacode.kframework.exception.ServerInternalErrorException;
import com.kuaimacode.kframework.mybatis.mapper.agent.SysAgentMapper;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgent;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgentOrder;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgentRole;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgentUser;
import com.kuaimacode.kframework.mybatis.models.finance.AgentAccountDetail;
import com.kuaimacode.kframework.mybatis.models.sysparam.SysParam;
import com.kuaimacode.kframework.util.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @date 2019/03/31
 */
@Service
public class SysAgentService extends ServiceImpl<SysAgentMapper, SysAgent> {

    @Autowired
    private SysAgentUserService agentUserService;
    @Autowired
    private SysAgentRoleService agentRoleService;
    @Autowired
    private SysParamService sysParamService;
    @Autowired
    private AgentAccountDetailService agentAccountDetailService;

    /**
     * 分页查找所有的数据
     *
     * @param pageNum  当前页码，从1开始
     * @param pageSize 一页显示多少行
     * @return
     */
    public PageInfo<SysAgent> findAll(int pageNum, int pageSize, SysAgent searchAgent) {
//        List<SysAdminUser> adminUsers = adminUserService.list();
        PageHelper.startPage(pageNum, pageSize);
        QueryWrapper<SysAgent> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(searchAgent.getName())) {
            wrapper.like("name", searchAgent.getName());
        }
        if (StringUtils.isNotBlank(searchAgent.getContact())) {
            wrapper.like("contact", searchAgent.getContact());
        }
        if (StringUtils.isNotBlank(searchAgent.getId())) {
            wrapper.eq("id", searchAgent.getId());
        }
        if (StringUtils.isNotBlank(searchAgent.getPhone())) {
            wrapper.like("phone", searchAgent.getPhone());
        }
        if (searchAgent.getStat() != null) {
            wrapper.eq("stat", searchAgent.getStat());
        }
        wrapper.orderByAsc("stat");
        List<SysAgent> datas = baseMapper.selectList(wrapper);
        /*if (adminUsers != null) {
            Optional.ofNullable(datas)
                    .ifPresent(sysAgents -> sysAgents.forEach(sysAgent -> {
                        adminUsers.stream().filter(adminUser -> adminUser.getUserId().equals(sysAgent.getOpenBy()))
                                .findFirst().ifPresent(adminUser -> sysAgent.setOpenName(adminUser.getUserName()));
                    }));
        }*/
        return new PageInfo<>(datas);
    }

    /**
     * 开通分站
     *
     * @param agentId
     * @return
     */
    public boolean openAgent(String agentId) {
        SysAgent agent = baseMapper.selectById(agentId);
        if (agent == null) {
            throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
        }

        SysAgent updateAgent = new SysAgent();
        updateAgent.setId(agentId);
        updateAgent.setOpenAt(new Date());
        updateAgent.setOpenBy(SessionUtil.getUserId());
        updateAgent.setStat(0);
        return baseMapper.updateById(updateAgent) == 1;
    }

    public boolean updateAgent(SysAgent agent) {
        SysAgent existsAgent = getById(agent.getId());
        Optional.ofNullable(existsAgent)
                .orElseThrow(() -> new ServerInternalErrorException(ErrorEnum.AGENT_NOT_EXISTS));
        if (StringUtils.isBlank(agent.getPhone())) {
            throw new ServerInternalErrorException(ErrorEnum.AGENT_PHONE_NOT_NULL);
        }
        //开通分站
        if (agent.getStat() != null && agent.getStat() == 0 && existsAgent.getStat() != 0) {
            //校验手机号是否存在管理员
            if (agentUserService.findByUserName(agent.getPhone()) != null) {
                throw new ServerInternalErrorException(ErrorEnum.AGENT_CONTACT_PHONE_EXISTS);
            }
            agent.setOpenAt(new Date());
            agent.setOpenBy(SessionUtil.getUserId());
            //检查分站角色是否存在
            Long roleId;
            if (agentRoleService.countByAgentId(agent.getId()) < 1) {
                //创建分站角色
                SysAgentRole agentRole = new SysAgentRole();
                agentRole.setIsAvailable(true);
                agentRole.setIsCustom(false);
                agentRole.setAgentId(agent.getId());
                agentRole.setRoleName("管理员");
                roleId = agentRoleService.createRole(agentRole);
                agentRoleService.grantAllPermission(roleId.toString());
            } else {
                //查询某个分站最小的角色ID
                SysAgentRole agentRole = agentRoleService.getSmallRole(agent.getId());
                roleId = agentRole.getRoleId();
            }
            if (agentUserService.findByUserNameAgentId(agent.getPhone(), agent.getId()) == null) {
                //默认联系人为管理员
                SysAgentUser agentUser = new SysAgentUser();
                agentUser.setAgentId(agent.getId());
                agentUser.setIsLocked(false);
                agentUser.setPositionJob("管理员");
                agentUser.setRealName(agent.getContact());
                agentUser.setEmail("");
                agentUser.setCellphone(agent.getPhone());
                agentUser.setTel("");
                agentUser.setUserName(agent.getPhone());
                agentUser.setPassword(SysAgentUserPasswordConstants.DEFAULT_PASSWORD);
                agentUserService.save(agentUser, Lists.newArrayList(roleId.toString()));
            }
            //插入系统参数
            //先删除
            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.eq("agent_id",agent.getId());
            sysParamService.remove(updateWrapper);

            List<SysParam> sysParams = new ArrayList<>();
            for(int i=0;i<Constant.SYS_PARAM_INIT_KEY.length;i++){

                SysParam sysParam = new SysParam();
                sysParam.setAgentId(agent.getId());
                sysParam.setValue(Constant.SYS_PARAM_INIT_VALUE[i]);
                sysParam.setName(Constant.SYS_PARAM_INIT_KEY[i]);
                sysParam.setNote(Constant.SYS_PARAM_INIT_NOTE[i]);
                sysParams.add(sysParam);
            }
            sysParamService.saveBatch(sysParams);

        }
        return updateById(agent);
    }

    /**
     * 分站是否存在
     *
     * @param agentId
     * @return
     */
    public boolean hasAgent(String agentId) {
        return baseMapper.selectById(agentId) == null;
    }

    /**
     * 关闭分站
     *
     * @param agentId
     * @return
     */
    @Transactional
    public boolean closeAgent(String agentId) {
        SysAgent agent = baseMapper.selectById(agentId);
        if (agent == null) {
            throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
        }

        //关闭分站
        //删除分站默认管理员
        QueryWrapper<SysAgentUser> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", agent.getPhone());
        agentUserService.remove(wrapper);

        SysAgent updateAgent = new SysAgent();
        updateAgent.setId(agentId);
        updateAgent.setStat(1);
        return baseMapper.updateById(updateAgent) == 1;
    }

    public void resetPassword(String agentId) {
        SysAgent agent = getById(agentId);
        if (StringUtils.isBlank(agent.getPhone())) {
            throw new ServerInternalErrorException(ErrorEnum.AGENT_PHONE_NOT_NULL);
        }

        SysAgentUser agentUser = agentUserService.findByUserNameAgentId(agent.getPhone(), agentId);
        Optional.ofNullable(agentUser).orElseThrow(() -> new ServerInternalErrorException(ErrorEnum.AGENT_ADMIN_NOT_EXISTS));
        agentUserService.resetPassword(agentUser.getUserId());
    }

    public int openAgentCount() {
        QueryWrapper<SysAgent> wrapper = new QueryWrapper<>();
        wrapper.eq("stat", 0);
        return baseMapper.selectCount(wrapper);
    }

    /**
     * 分站总余额
     * @return
     */
    public BigDecimal totalBalance() {
        QueryWrapper<SysAgent> wrapper = new QueryWrapper<>();
        wrapper.eq("stat", 0);

        List<SysAgent> list = baseMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return BigDecimal.ZERO;
        }
        BigDecimal amount = new BigDecimal(0);
        for (SysAgent sysAgent : list) {
            amount = amount.add(sysAgent.getBalance());
        }
        return amount;
    }

    /**
     * 更新分站账户余额
     */
    public int updateBal(String agentId, String inOut, BigDecimal amount){
        return baseMapper.updateBalance(agentId,inOut,amount);

    }

    /**
     * 改变账户余额
     * @param agentId
     * @param inOutEnum
     * @param amount
     * @param typeEnum
     * @param tranDesc
     * @param tranId
     * @return
     */
    public int changeBalance(String agentId, Constant.InOutEnum inOutEnum, BigDecimal amount, Constant.AgentAccountTranTypeEnum typeEnum, String tranDesc, String tranId) {
        AgentAccountDetail insert = new AgentAccountDetail();
        insert.setAgentId(agentId);
        insert.setInOut(inOutEnum.getCode().toString());
        insert.setTranType(typeEnum.getCode().toString());
        insert.setAmount(amount);
        //提现类型，金额减少
        if (typeEnum == Constant.AgentAccountTranTypeEnum.DRAW) {
            insert.setTranBal(getById(agentId).getBalance().subtract(amount));
        } else {
            insert.setTranBal(getById(agentId).getBalance().add(amount));
        }
        insert.setTranDesc(tranDesc);
        insert.setTranTime(new Date());
        insert.setTranId(tranId);
        insert.setStatus("0");
        //记录交易明细
        agentAccountDetailService.save(insert);
        return baseMapper.updateBalance(agentId, inOutEnum.getCode().toString(), amount);
    }

    public Map<String, BigDecimal> findCollectInfo(AgentOrderReq orderReq) {
        return baseMapper.findCollectInfo(orderReq.getAgentId(), orderReq.getTranType(),
                DateUtil.stringtoDate(orderReq.getStartTime(), DateUtil.LONG_DATE_FORMAT),
                DateUtil.stringtoDate(orderReq.getEndTime(), DateUtil.LONG_DATE_FORMAT));
    }

    /**
     * 分站管理页面查看订单数据详情
     * @param orderReq
     * @param pageInfo
     * @return
     */
    public List<AgentOrderResp> findAgentOrderDetail(AgentOrderReq orderReq, int pageNum, int pageSize) {
        if (orderReq.getTranType() == null) {
            orderReq.setTranType("");
        }
        List<SysAgentOrder> agentOrderList = baseMapper.findAgentOrderDetail(orderReq.getAgentId(), orderReq.getTranType(),
                DateUtil.stringtoDate(orderReq.getStartTime(), DateUtil.LONG_DATE_FORMAT),
                DateUtil.plus(DateUtil.stringtoDate(orderReq.getEndTime(), DateUtil.LONG_DATE_FORMAT), DateUtil.DateEnum.DAY, 1), 0, 50);

        Map<String, AgentOrderResp> orderRespMap = DateUtil.getBetweenDate(orderReq.getStartTime(), orderReq.getEndTime())
                .stream().collect(Collectors.toMap(date -> date, date -> {
                    AgentOrderResp resp = AgentOrderResp.defaultInstance();
                    resp.setTranTime(DateUtil.stringtoDate(date, DateUtil.LONG_DATE_FORMAT));
                    resp.setTranType(orderReq.getTranType());
                    resp.setTranType(resp.exchangeTranType());
                    return resp;
                }));
        Optional.ofNullable(agentOrderList)
                .ifPresent(list -> list.forEach(sysAgentOrder -> {
                    AgentOrderResp resp = orderRespMap.get(sysAgentOrder.getTranTime());
                    if (resp == null) {
                        return;
                    }
                    switch (sysAgentOrder.getType()) {
                        case "platform":
                            resp.setPlatformIncome(sysAgentOrder.getAgentMoney());
                            break;
                        case "agent":
                            resp.setAgentIncome(sysAgentOrder.getAgentMoney());
                            break;
                        case "master":
                            resp.setMasterIncome(sysAgentOrder.getAgentMoney());
                            break;
                        case "valid_count":
                            resp.setValidCount(sysAgentOrder.getAgentMoney().longValue());
                            break;
                        case "invalid_count":
                            resp.setInvalidCount(sysAgentOrder.getAgentMoney().longValue());
                            break;
                        case "coupon_amount":
                            resp.setOffer(sysAgentOrder.getAgentMoney());
                            break;
                        default:
                    }
                }));
        List<AgentOrderResp> orderRespList = orderRespMap.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList());
        Collections.sort(orderRespList, (order1, order2) -> {
            if (order1.getTranTime().getTime() < order2.getTranTime().getTime()) {
                return 1;
            } else if (order1.getTranTime().getTime() > order2.getTranTime().getTime()) {
                return -1;
            } else {
                return 0;
            }
        });
        return orderRespList;
    }

    /**
     * 分站数据导出
     * @param orderReq
     * @param pageNum
     * @param pageSize
     * @param response
     */
    public void agentOrderExport(AgentOrderReq orderReq, int pageNum, int pageSize, HttpServletResponse response) {
        List<AgentOrderResp> list = this.findAgentOrderDetail(orderReq, pageNum, pageSize);

        List<List<String[]>> dataLists = new ArrayList<>();
        List<String[]> oneList = new ArrayList<>();
        String[] headers = {"日期", "业务类型", "平台收益", "分站收益", "师傅收益", "优惠款", "未入账", "有效单数", "取消单数"};
        oneList.add(headers);
        Optional.ofNullable(list)
                .ifPresent(resps -> resps.forEach(resp -> {
                    String[] values = new String[]{DateUtil.format(resp.getTranTime(), DateUtil.LONG_DATE_FORMAT), resp.exchangeTranType(),
                            resp.getPlatformIncome().toString(), resp.getAgentIncome().toString(), resp.getMasterIncome().toString(), resp.getOffer().toString(),
                            resp.getNotAccounted().toString(), resp.getValidCount().toString(), resp.getInvalidCount().toString()};
                    oneList.add(values);
                }));
        dataLists.add(oneList);

        ExcelUtils excelUtils = ExcelUtils.initialization();
        excelUtils.setDataLists(dataLists);
        excelUtils.setSheetName(new String[]{"分站数据"});
        excelUtils.setResponse(response);
        // 执行导出
        excelUtils.exportForExcelsOptimize();
    }
}

